var aoPostLoadFormCallback = aoPostLoadFormCallback || {};
var aoPostSubmitFormCallback = aoPostSubmitFormCallback || {};
var _aoFormLoader = (function(w){
var stylesLoaded = false;
var captchaLoaded = false;
var gfLoaded = false;
var htmlId = false;
var formsLoadedCount = 0;
var formsCount = 0;
var scheme = document.location.protocol + "//";
function populateDateField(inputElem, value) {
if(!value || !inputElem) {
return;
}
var dateWrapper = inputElem.parentElement;
var dateElements = dateWrapper.querySelectorAll('input.ao-form-field-date');
var amPm;
if (value.indexOf("AM")) {
value = value.replace("AM", "");
amPm = "AM";
} else if (value.indexOf("PM")) {
value = value.replace("PM", "");
amPm = "PM";
}
var dateFormat = value.split(/[:\/\s]+/);
// Populate all date input fields
dateElements.forEach(function(elem, index) {
elem.value = dateFormat[index] || '';
});
// Populate AM/PM dropdown
if(amPm && dateWrapper.querySelector("option[value='" + amPm + "']")) {
dateWrapper.querySelector("option[value='" + amPm + "']").selected = true;
}
}
var loadForm = function(options){
formsCount += 1; //increment for each form that is on the page
loadStylesheet(options);
var previewMarkup = '
Unable to preview form, it has reached the submission cap or expired.
';
var oReq = new XMLHttpRequest();
oReq.onload = function (e) {
var response;
if (e.target.responseType === 'json') {
response = e.target.response || false;
} else {
response = (e.target.response) ? JSON.parse(e.target.response) : false;
}
if(!response){
return false;
} else if (response && typeof response.processedTemplate === 'undefined' && response.linkURL && response.linkURL != '') {
window.location = response.linkURL;
return false;
}
var idArr = options.id.split(":");
htmlId = (options.uniqueId) ? options.id + options.uniqueId : options.id;
divId = (options.uniqueId) ? idArr[0] + options.uniqueId : idArr[0];
var existingDiv = document.getElementById('aoform-' + divId);
if(existingDiv)
existingDiv.parentNode.removeChild(existingDiv);
var div = document.createElement('div');
var scriptTag = document.getElementById('aoform-script-' + htmlId);
div.id = 'aoform-' + divId;
div.style.visibility = "hidden";
scriptTag.parentNode.insertBefore(div, scriptTag);
div.innerHTML = response && response.processedTemplate ? response.processedTemplate : previewMarkup;
formsLoadedCount += 1; //increment for when a form is loaded onto the page
if(response.formProperties && ! response.formProperties.invalidDomain){
//Set referrer
div.querySelector("input[name='ao_refurl']").value = document.referrer;
div.querySelector("input[name='ao_target']").value = window.location.href;
div.querySelector("input[name='ao_refemail']").value = getParameterByName("aoRefEmail");
div.querySelector("input[name='ao_campid']").value = getParameterByName("cmpid");
div.querySelector("input[name='ao_gatedpage']").value = getParameterByName("ao_gatedpage");
div.querySelector("input[name='ao_gatedasset']").value = getParameterByName("ao_gatedasset");
var ajaxSubmit = response && response.formProperties && response.formProperties.hasAjaxResponse ? response.formProperties.hasAjaxResponse : false;
loadCaptcha();
updateTabIndexes();
loadGoogleFonts();
formValidationEvents(div, ajaxSubmit);
// Form Prefill
if ( response.prefill && Object.keys( response.prefill ).length > 0 ) {
var fields = Object.keys( response.prefill );
fields.forEach( function( field ) {
var input = div.querySelector("input[name='" + field + "']");
var select = div.querySelector("select[name='" + field + "']");
var textarea = div.querySelector("textarea[name='" + field + "']");
if ( ! input && ! select && ! textarea ) {
return;
}
if(input){
if(input.type== "radio"){
var radios = div.querySelectorAll("input[name='" + field + "']");
for(var i = 0; i 1) {
var actonForms = document.querySelectorAll("form.ao-form");
var startingTabIndex = 100;
for(var i = 1; i -1 ) {
formId = formId.substr(0, formId.indexOf(':'));
}
if(options.uniqueId){
formId += (options.uniqueId) ? options.uniqueId : '';
}
var formByID = document.getElementById("aoform-" + formId);
watchFields.forEach( function ( field ) {
var fieldElm = document.getElementById(field)
if(!fieldElm){
fieldElm = formByID.querySelector("#block-" + field);
}
if(fieldElm){
if(fieldElm.nodeName == "DIV" && fieldElm.classList.contains("ao-combo-layout")) {
var radios = fieldElm.querySelectorAll("input[type='radio'],input[type='checkbox']");
fact.data[field] = "";
for (var i = 0; i < radios.length; i++) {
if (radios[i].checked) {
fact.data[field] += radios[i].value;
}
}
}else if(fieldElm.nodeName=="DIV" && fieldElm.classList.contains("ao-date-block")) {
/*
Get parent div of a date control, then get all "ao-form-field-date" objects from that div
Build a date object from those, and set as value. If it's an invalid date, value = null
Date fields are tagged with id "date--"
*/
var dtMonth = "";
var dtDay = "";
var dtYear = "";
var txtInputs = fieldElm.querySelectorAll("input[type='text']");
var dtMonth = "";
var dtDay = "";
var dtYear = "";
var txtInputs = fieldElm.querySelectorAll("input[type='text']");
var hasDateError = false;
for(var i=0; i < txtInputs.length; i++){
if (txtInputs[i].value == ""){
hasDateError = true;
}
switch(txtInputs[i].getAttribute("data-format")){
case "DD":
dtDay = txtInputs[i].value;
break;
case "MM":
dtMonth = txtInputs[i].value;
break;
case "YY":
dtYear = txtInputs[i].value;
break;
case "YYYY":
dtYear = txtInputs[i].value;
break;
}
}
if (!hasDateError){
fact.data[field] = dtYear + dtMonth + dtDay;
}else{
fact.data[field] = "";
}
} else {
fact.data[field] = fieldElm.value;
}
}
});
var body = {
payload : {
accountId : accountId,
key : formId,
facts : [fact]
}
};
var xhr = new XMLHttpRequest();
xhr.open( 'PUT', scheme + options.domain + '/acton/openapi/form/v1/' + options.accountId + '/' + formId + '/factEval' );
xhr.setRequestHeader( 'Content-Type', 'application/json' );
xhr.send( JSON.stringify( body ) );
// Check if the active element lost focus due to conflicting conditionals such as hide / show,
// Give focus back if lost focus and not hidden
function refocusIfLostFocus(activeEl) {
if(activeEl !== document.activeElement && !activeEl.classList.contains("ao-condition-hide")) {
activeEl.focus();
}
}
xhr.onreadystatechange = function() {
if ( xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200 ) {
// Get element that has focus before hiding/showing elements
const activeEl = document.activeElement;
var response = JSON.parse(xhr.response);
//Go through the non true results first and set base display
for(var i=0; i -1 ) {
formId = formId.substr( 0, formId.indexOf(':') )
}
if ( !watchFields ){
//Show form on initial load
containerDiv.style.visibility = "visible";
return;
}
//Remove duplicate watches
var watchFieldsSeen = {};
var watchFieldsUnique = watchFields.filter(function(item) {
return watchFieldsSeen.hasOwnProperty(item) ? false : (watchFieldsSeen[item] = true);
});
watchFieldsUnique.forEach( function ( field ) {
var el = document.getElementById(field)
/*If fieldElm is not found, will need to check for alternatives
* Most likely candidate, if "date", look for a the block, then a named child
* EG: div: block-fieldID child named date*/
if(!el){
el = containerDiv.querySelector("#block-" + field);
}
if(el){
if(el.nodeName == "SELECT"){
el.addEventListener( 'change', function ( event ) {
// put a debounce in here so we're making requests on every keystroke
var result = evalFacts( accountId, formId, watchFieldsUnique, options );
}, false );
} else if(el.nodeName == "DIV" && el.classList.contains("ao-combo-layout")) {
var inputs = el.querySelectorAll("input");
for (i = 0; i < inputs.length; i++) {
inputs[i].addEventListener('click', function (event) {
// put a debounce in here so we're making requests on every keystroke
if (el.classList.contains("ao-form-error")) {
el.classList.remove("ao-form-error");
}
var result = evalFacts(accountId, formId, watchFieldsUnique, options);
}, false);
}
}
else if(el.nodeName == "DIV" && el.classList.contains("ao-date-block")) {
var inputs = el.querySelectorAll("input");
for (i = 0; i < inputs.length; i++) {
if(!inputs[i].classList.contains("ao-form-field-date-input")) {
inputs[i].addEventListener( 'keyup', debounce(function () {
evalFacts( accountId, formId, watchFieldsUnique, options );
}, 500), false);
}
}
} else {
el.addEventListener( 'keyup', debounce(function () {
evalFacts( accountId, formId, watchFieldsUnique, options );
}, 500), false);
}
}
});
//Initial Load
evalFacts( accountId, formId, watchFieldsUnique, options, containerDiv);
};
function getParameterByName(name) {
url = window.location.href;
name = name.replace(/[\[\]]/g, "\\$&");
var regex = new RegExp("[?&]" + name + "(=([^]*)|&|#|$)", "i"),
results = regex.exec(url);
if (!results) return null;
if (!results[2]) return '';
return decodeURIComponent(results[2].replace(/\+/g, " "));
}
var formValidationEvents = function(form, ajaxSubmit){
var actonForms = form.querySelectorAll("form.ao-form");
var findRecaptchaElements = function(form, hasError){
//Find the recaptcha wrapper
var recaptchaWrapper = form.querySelectorAll(".ao-recaptcha-error-wrapper");
if (recaptchaWrapper.length > 0) {
if (hasError) {
//If found and has error then apply the style that will show the red border around the element
recaptchaWrapper[0].classList.add("ao-recaptcha-error");
} else {
//Remove the style because the user has attempted to work with the recaptcha again
recaptchaWrapper[0].classList.remove("ao-recaptcha-error");
}
}
//Find the element that will show the failed to completed the recaptcha
var recaptchaMsg = form.querySelectorAll(".ao-recaptcha-error-robot-message");
if (recaptchaMsg.length > 0) {
if (hasError) {
//Show the text
recaptchaMsg[0].style.display = "block";
} else {
//Hide the text
recaptchaMsg[0].style.display = "none";
}
}
};
var invalidCaptcha = function(form){
//Wait for the Recaptcha widget before we build the error logging aorund it
setTimeout(function () {
//Apply the styling that says the user failed to validate the Recaptcha
findRecaptchaElements(form, true);
}, 1000);
//Keep checking if the user has attempted to validate the Recaptcha, we will know because the token will go into the hidden input the cap sends on submission
var recaptchaInterval = setInterval(function () {
var recaptchaBoxCode = form.querySelectorAll("#g-recaptcha-response");
//If we find the element and the value is not empty then a user has interacted with the cap, validation happens on the submission not now
if (recaptchaBoxCode.length > 0 && recaptchaBoxCode[0].value !== '') {
//Remove the styling that was generated by the error
findRecaptchaElements(form, false);
//Remove the interval that listens for the check
window.clearInterval(recaptchaInterval);
}
}, 2000);
};
for(var i=0; i= this.getAttribute('maxlength') ){
var node = this.nextSibling;
while (node) {
if (node.tagName=='INPUT') {
node.focus();
break;
}
node = node.nextSibling;
}
}
})
})(currentField);
}
//check if the form id matches the param sent back on the user submission redirect of the formid that failed user submit
if(htmlId.indexOf(getParameterByName("validRecaptcha")) > -1) {
invalidCaptcha(form);
}
if(actonForms[i].hasAttribute('data-validate-blur')){
for (var j = 0; j < validationFields.length; j++) {
var currentField = validationFields[j];
(function(currentField) {
currentField.addEventListener( "focusout", function(){
validateField(currentField);
});
currentField.addEventListener( "change", function(){
validateField(currentField);
});
})(currentField);
}
}
//Set On Submit Event
var currentForm = actonForms[i];
(function(currentForm, ajaxSubmit) {
currentForm.addEventListener("submit", function(e){
var passedValidation = true;
for (var i = 0; i < validationFields.length; i++) {
//Check visibility of field. offsetWidth/Height of null = not visible
if (!!( validationFields[i].offsetWidth || validationFields[i].offsetHeight || validationFields[i].getClientRects().length )){
if (!validateField(validationFields[i])) {
passedValidation = false;
}
}
}
for (var i = 0; i < validationCombos.length; i++) {
//Check visibility of field. offsetWidth/Height of null = not visible
if (!!( validationCombos[i].offsetWidth || validationCombos[i].offsetHeight || validationCombos[i].getClientRects().length )) {
if (!validateField(validationCombos[i], {isCombo: true})) {
passedValidation = false;
}
}
}
for (var i = 0; i < validationDates.length; i++) {
if (!!( validationDates[i].offsetWidth || validationDates[i].offsetHeight || validationDates[i].getClientRects().length )) {
if (!validateField(validationDates[i], {isDate: true})) {
passedValidation = false;
}
}
}
for (var i = 0; i < submitBlock.length; i++) {
if (!( submitBlock[i].offsetWidth || submitBlock[i].offsetHeight || submitBlock[i].getClientRects().length )) {
passedValidation = false;
}
}
for (var i = 0; i < dynamicHiddenFields.length; i++) {
var fieldMatch = dynamicHiddenFields[i].getAttribute("data-dynamic-match");
var fieldDefault = dynamicHiddenFields[i].getAttribute("data-dynamic-default");
dynamicHiddenFields[i].value = getParameterByName(fieldMatch) || fieldDefault;
}
//Set Date fields
var dateBlocks = currentForm.querySelectorAll(".ao-date-block");
for(var i = 0; i < dateBlocks.length; i++){
var dateBlock = dateBlocks[i];
var dateBlockInput = dateBlock.querySelector(".ao-form-field-date-input");
var dateBlockPartials = dateBlock.querySelectorAll(".ao-form-field-date");
var dateVal = "";
for(var j=0; j -1 ) ? formId.substr( 0, formId.indexOf(':') ) : formId;
if(aoPostSubmitFormCallback[formId] && typeof aoPostSubmitFormCallback[formId] === 'function'){
aoPostSubmitFormCallback[formId]();
}
//Inline gated content URL is only used in the case of iOS devices
var inlineURL = document.getElementById("ao_inline-" + formId);
if (inlineURL && isIOS()) {
window.location = inlineURL.value;
}
}
};
req.open(currentForm.method, currentForm.action);
req.withCredentials = true;
req.send(data);
}
})
})(currentForm, ajaxSubmit);
}
};
function isIOS() {
return /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
}
var disableSubmitButtons = function(submitButtons) {
for (var i=0; i < submitButtons.length; i++) {
submitButtons[i].disabled = true;
}
};
// special chracter escaped regex from https://emailregex.com/ with capital letter allowance added
var validEmailRegex="^(?:[a-zA-Z0-9!#$%&\'*+/=?^_`{|}~-]+(?:\\.[a-zA-Z0-9!#$%&\'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-zA-Z0-9-]*[a-zA-Z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])$"
var validEmailRegexObj = new RegExp(validEmailRegex);
var validateField = function(field, options){
var o = options ? options : {};
var validators = field.getAttribute('data-validator').split("|");
var errorSpan = field.parentNode.querySelector(".ao-form-error-message");
errorSpan.innerHTML = " ";
var errorMessageArr = [];
var errorMessageOverrideArr = (field.getAttribute('data-error-message')) ? field.getAttribute('data-error-message').split("::") : false;
field.classList.remove("ao-form-error");
for(var i=0; i field.getAttribute('maxlength') || 0) {
hasErrors = true;
}
break;
case "minyear":
if(o.isDate) {
var validationDateFields = field.querySelectorAll("input");
for (var m = 0; m < validationDateFields.length; m++) {
var dateType = validationDateFields[m].getAttribute("placeholder");
switch(dateType){
case "YY":
case "YYYY":
if(validationDateFields[m].value < field.getAttribute('data-minyear') || 0 ){
validationDateFields[m].classList.add("ao-form-error");
hasErrors = true;
} else {
validationDateFields[m].classList.remove("ao-form-error");
}
break;
}
}
}
break;
case "maxyear":
if(o.isDate) {
var validationDateFields = field.querySelectorAll("input");
for (var m = 0; m < validationDateFields.length; m++) {
var dateType = validationDateFields[m].getAttribute("placeholder");
switch(dateType){
case "YY":
case "YYYY":
if(validationDateFields[m].value > field.getAttribute('data-maxyear') || 0 ){
validationDateFields[m].classList.add("ao-form-error");
hasErrors = true;
} else {
validationDateFields[m].classList.remove("ao-form-error");
}
break;
}
}
}
break;
case "match":
var matchField = document.getElementById(field.getAttribute('data-match'));
if (field && matchField && field.value != matchField.value ) {
hasErrors = true;
}
break;
case "phoneus":
if(field.value && !/^(\+?1?)?(-?\s?\.?)?(\([2-9]([02-9]\d|1[02-9])\)|[2-9]([02-9]\d|1[02-9]))-?\s?\.?[2-9]([0-9]{2})\s?-?\.?\d{4}$/.test(field.value)) {
hasErrors = true;
}
break;
case "phoneint":
if(field.value && !/^\+(?:[0-9] ?){6,14}[0-9]$/.test(field.value)) {
hasErrors = true;
}
case "phoneall":
if(field.value && !/(^(\+?1?)?(-?\s?\.?)?(\([2-9]([02-9]\d|1[02-9])\)|[2-9]([02-9]\d|1[02-9]))-?\s?\.?[2-9]([0-9]{2})\s?-?\.?\d{4}$)|(^\+(?:[0-9] ?){6,14}[0-9]$)/.test(field.value)) {
hasErrors = true;
}
break;
case "url":
if(field.value && !/(http|ftp|https):\/\/[\w-]+(\.[\w-]+)+([\w.,@?^=%&:/~+#-]*[\w@?^=%&/~+#-])?/.test(field.value)) {
hasErrors = true;
}
break;
case "custom":
var pattern = new RegExp(field.getAttribute('data-custom'));
if (field.value && !pattern.test(field.value)) {
hasErrors = true;
}
break;
}
if (hasErrors){
if(! o.isDate)
field.classList.add("ao-form-error");
field.setAttribute("aria-invalid", "true");
errorSpan.innerHTML = ( errorMessageArr[validationType] ) ? errorMessageArr[validationType] : "Invalid";
return false;
}
}
return true;
};
function debounce(a,b,c){var d;return function(){var e=this,f=arguments;clearTimeout(d),d=setTimeout(function(){d=null,c||a.apply(e,f)},b),c&&!d&&a.apply(e,f)}}
return {
load: function(opts) {
loadForm(opts);
},
loadAll: function(){
for(var i=0; i